package com.binbinyl.helper.network

import com.google.gson.GsonBuilder
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

/**
 * 网络管理类
 */
object NetManager {
    private const val DEFAULT_CONNECT_TIMEOUT_SEC = 10L
    private const val DEFAULT_READ_TIMEOUT_SEC = 10L
    private const val DEFAULT_WRITE_TIMEOUT_SEC = 10L

    private val mProviderMap = HashMap<String, NetProvider>()
    private val mRetrofitMap = HashMap<String, Retrofit>()
    private val mClientMap = HashMap<String, OkHttpClient>()
    //通过该类提供的配置信息，初始化网络框架实例
    private var defaultProvider: NetProvider? = null

    @JvmOverloads
    fun getRetrofit(baseUrl: String, netProvider: NetProvider? = null): Retrofit {
        var provider = netProvider

        if (empty(baseUrl)) {
            throw IllegalStateException("baseUrl can not be null")
        }

        if (mRetrofitMap[baseUrl] != null) {
            return mRetrofitMap[baseUrl]!!
        }

        if (provider == null) {
            provider = mProviderMap[baseUrl]
            if (provider == null) {
                provider = defaultProvider;
            }
        }
        checkProvider(provider)

        val gson = GsonBuilder()
                .setDateFormat("yyyy-MM-dd HH:mm:ss")
                .setLenient()
                .create()

        val builder = Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(getClient(baseUrl, provider!!))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))


        val retrofit = builder.build()
        mRetrofitMap[baseUrl] = retrofit
        mProviderMap[baseUrl] = provider

        return retrofit
    }

    private fun empty(baseUrl: String?): Boolean {
        return baseUrl == null || baseUrl.isEmpty()
    }

    private fun empty(list: Array<Interceptor>?): Boolean {
        return list == null || list.isEmpty()
    }

    private fun checkProvider(provider: NetProvider?) {
        if (provider == null) {
            throw IllegalStateException("must register provider first")
        }
    }

    fun getClient(baseUrl: String, provider: NetProvider?): OkHttpClient {

        if (empty(baseUrl)) {
            throw IllegalStateException("baseUrl can not be null")
        }

        if (mClientMap[baseUrl] != null) {
            return mClientMap[baseUrl]!!
        }

        checkProvider(provider)

        val builder = OkHttpClient.Builder()

        builder.connectTimeout(
                if (provider!!.configConnectTimeoutSecs() != 0L)
                    provider.configConnectTimeoutSecs()
                else
                    DEFAULT_CONNECT_TIMEOUT_SEC
                , TimeUnit.SECONDS)

        builder.readTimeout(
                if (provider.configReadTimeoutSecs() != 0L)
                    provider.configReadTimeoutSecs()
                else
                    DEFAULT_READ_TIMEOUT_SEC
                , TimeUnit.SECONDS)

        builder.writeTimeout(
                if (provider.configWriteTimeoutSecs() != 0L)
                    provider.configWriteTimeoutSecs()
                else
                    DEFAULT_WRITE_TIMEOUT_SEC
                , TimeUnit.SECONDS)

        val cookieJar = provider.configCookie()
        if (cookieJar != null) {
            builder.cookieJar(cookieJar)
        }

        //interceptors
        val requestHandler = provider.configHandler()
        if (requestHandler != null) {
            builder.addInterceptor(NetInterceptor(requestHandler))
        }

        val interceptors = provider.configInterceptors()
        if (!empty(interceptors)) {
            for (interceptor in interceptors!!) {
                builder.addInterceptor(interceptor);
            }
        }

        if (provider.configLogEnable()) {
            val loggingInterceptor = HttpLoggingInterceptor()
            loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
            builder.addInterceptor(loggingInterceptor)
        }

        provider.configHttps(builder)

        val client = builder.build()
        mClientMap[baseUrl] = client;
        mProviderMap[baseUrl] = provider

        return client
    }

    fun registerNetProvider(provider: NetProvider) {
        NetManager.defaultProvider = provider
    }

    operator fun <S> get(baseUrl: String, service: Class<S>): S {
        return getRetrofit(baseUrl).create(service)
    }
}



































